package com.bit.cfdi.web.development.utils;

import java.util.List;

import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import com.bit.cfdi.web.constants.NavInfrastructure;
import com.bit.cfdi.web.dao.NegocioDAO;
import com.bit.cfdi.web.dao.UsuarioDAO;
import com.bit.cfdi.web.dao.UsuarioNegocioDAO;
import com.bit.cfdi.web.domain.Contacto;
import com.bit.cfdi.web.domain.DBConstants;
import com.bit.cfdi.web.domain.DatosFiscales;
import com.bit.cfdi.web.domain.Direccion;
import com.bit.cfdi.web.domain.ModulosUsuario;
import com.bit.cfdi.web.domain.Negocio;
import com.bit.cfdi.web.domain.Persona;
import com.bit.cfdi.web.domain.Sucursal;
import com.bit.cfdi.web.domain.Usuario;
import com.bit.cfdi.web.domain.UsuarioNegocio;
import com.bit.cfdi.web.services.LoginService;
import com.bit.cfdi.web.session.SessionUtils;
import com.bit.cfdi.web.utils.EncryptionUtils;
import com.bit.cfdi.web.utils.PasswordGenerator;

@Repository
public class AutoLoginService {
	
	private Logger log = LogManager.getLogger(this.getClass().getName());
	
	private static final String AUTOLOGIN_PROPERTY = "AutoLogin";
	private static final String BUSINESS_AUTO_CREATION = "BusinessCreation";
	
	private static final String DUMMY_USER = "developer@domain.com";
	private static final String DUMMY_PASSWORD = "tHn92@TrOn";
	
	private static final String DUMMY_BUSINESS = "negocio1";
	
	@Autowired private LoginService loginService;
	@Autowired private UsuarioDAO usuarioDAO;
	@Autowired private NegocioDAO negocioDAO;
	@Autowired private UsuarioNegocioDAO usuarioNegocioDAO;
	@Autowired private EncryptionUtils encryptionUtils;
	@Autowired private PasswordGenerator passwordGenerator;
	@Autowired private SessionUtils sessionUtils;

	public boolean doAutoLogin() {
		log.info("Entering to auto-login");
		String value = System.getProperty(AUTOLOGIN_PROPERTY);
		if(!"yes".equals(value)) {
			log.info("skipping auto-login");
			return false;
		}
		Usuario dummyUser = usuarioDAO.getByEmail(DUMMY_USER);
		if(dummyUser == null) {
			saveDummyUser();
		}
		dummyUser = loginService.performLogin(DUMMY_USER, DUMMY_PASSWORD);
		if(dummyUser == null) {
			log.error("FATAL ERROR: couldn't perform autologin");
			log.info("skipping auto-login");
			return false;
		}
		if(sessionUtils.getFromSession(SessionUtils.USUARIO) != null) {
			return true;
		}
		if(!sessionUtils.addToSession(SessionUtils.USUARIO, dummyUser)) {
			log.error("FATAL ERROR: couldn't add dummy user to session");
			log.info("skipping auto-login");
			return false;
		}
		return true;
	}
	
	private void saveDummyUser() {
		log.info("Creating user with email: "+DUMMY_USER);
		String codigoActivacion = passwordGenerator.generatePassword(20);
		Usuario usuario = new Usuario();
		usuario.setEmail(DUMMY_USER);
		usuario.setPassword(encryptionUtils.stringEncryption(DUMMY_PASSWORD));
		usuario.setCodigoActivacion(codigoActivacion);
		usuario.setStatus(DBConstants.STATUS_ACTIVE);
		
		Persona persona = new Persona();
		usuario.setPersona(persona);
		
		Direccion direccion = new Direccion();
		persona.setDireccion(direccion);
		
		Contacto contacto = new Contacto();
		persona.setContacto(contacto);
		
		usuarioDAO.save(usuario);
		log.info("user: "+DUMMY_USER+ "was persisted");
	}
	
	public boolean doAutoBusiness() {
		log.info("Entering to business auto-creation");
		String value = System.getProperty(BUSINESS_AUTO_CREATION);
		if(!"yes".equals(value)) {
			log.info("skipping auto-login");
			return false;
		}
		Usuario usuario = (Usuario) sessionUtils
				.getFromSession(SessionUtils.USUARIO);
		if(usuario == null) {
			log.error("No user in session, there's no way to retrieve " +
					"business. Nothing to do");
			return false;
		}
		UsuarioNegocio toPutInSession = null;
		List<UsuarioNegocio> usuarioNegocios = usuarioNegocioDAO
				.getNegociosFromUsuario(usuario);
		if(usuarioNegocios.isEmpty()) {
			toPutInSession = saveDummyBusiness(usuario);
		}
		else {
			boolean hasAutoBusiness = false;
			for(UsuarioNegocio currentUsuarioNegocio : usuarioNegocios) {
				String nombreCurrentNegocio = currentUsuarioNegocio
						.getNegocio().getNombre();
				if(nombreCurrentNegocio != null && 
						DUMMY_BUSINESS.equals(nombreCurrentNegocio)) {
					toPutInSession = currentUsuarioNegocio;
					hasAutoBusiness = true;
				}
			}
			if(!hasAutoBusiness) {
				toPutInSession = saveDummyBusiness(usuario);
			}
		}
		if(toPutInSession == null) {
			log.info("There is no Usuario-negocio persisted, nothing to do");
			return false;
		}
		sessionUtils.addToSession(SessionUtils.NEGOCIO, toPutInSession
				.getNegocio());
		return true;
	}

	private UsuarioNegocio saveDummyBusiness(final Usuario usuario) {
		log.info("Creating business for dummy user, with name: "+DUMMY_BUSINESS);
		Negocio negocio = new Negocio();
		negocio.setNombre(DUMMY_BUSINESS);
		negocio.setStatus(DBConstants.STATUS_ACTIVE);
		
		DatosFiscales df = new DatosFiscales();
		negocio.setDatosFiscales(df);
		
		df.setDireccion(new Direccion());
		
		Sucursal sucursal = new Sucursal();
		sucursal.setNegocio(negocio);
		sucursal.setTipo(Sucursal.TIPO_SUCURSAL);
		sucursal.setDireccion(new Direccion());
		
		Sucursal matriz = new Sucursal();
		matriz.setNegocio(negocio);
		matriz.setTipo(Sucursal.TIPO_MATRIZ);
		matriz.setDireccion(new Direccion());
		
		negocio.getSucursales().add(sucursal);
		negocio.getSucursales().add(matriz);
		
		sessionUtils.addToSession(SessionUtils.NEGOCIO, negocio);
		log.info("Business persisted");
		
		log.info("Creating permissions between user and business");
		UsuarioNegocio usuarioNegocio = new UsuarioNegocio();
		usuarioNegocio.setUsuario(usuario);
		usuarioNegocio.setNegocio(negocio);
		usuarioNegocio.setStatus(DBConstants.STATUS_ACTIVE);
		
		for(String currentModule : NavInfrastructure.ALL_MODULES) {
			ModulosUsuario moduloUsuario = new ModulosUsuario();
			moduloUsuario.setNombreModulo(currentModule);
			moduloUsuario.setUsuarioNegocio(usuarioNegocio);
			usuarioNegocio.getAccesos().add(moduloUsuario);
		}
		
		negocio.getUsuariosNegocio().add(usuarioNegocio);
		
		negocioDAO.save(negocio);
		usuarioNegocioDAO.save(usuarioNegocio);
		log.info("permissions persisted");
		
		return usuarioNegocio;
	}
	
}
